package com.zmx.piglearn.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView
import com.zmx.piglearn.R
import java.lang.ref.WeakReference
import kotlin.math.max
import kotlin.math.min

class CircleImageView: AppCompatImageView {

    private val xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
    private var paint: Paint = Paint()
    private var maskBitmap: Bitmap? = null
    private var weakBitmap: Bitmap? = null

    companion object {
        val TYPE_CIRCLE = 0
        val TYPE_ROUND = 1
        val DEFAULT_BORDER_RADIUS = 10
    }
    private var type = TYPE_CIRCLE
    private var borderRadius = DEFAULT_BORDER_RADIUS

    constructor(context: Context): super(context, null) {}

    constructor(context: Context, attrs: AttributeSet): super(context, attrs) {
        paint.isAntiAlias = true
        // 取出 attrs 中我们为 View 设置的相关值
        val tArray = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView)
        borderRadius = tArray.getDimensionPixelSize(R.styleable.CircleImageView_Radius, DEFAULT_BORDER_RADIUS)
        type = tArray.getInt(R.styleable.CircleImageView_type, TYPE_CIRCLE)
        tArray.recycle()
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) {}

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        if (type == TYPE_CIRCLE) {
            val width = min(measuredWidth, measuredHeight)
            setMeasuredDimension(width, width)
        }
    }

    override fun onDraw(canvas: Canvas) {
        if (weakBitmap == null || weakBitmap!!.isRecycled) {
            if (drawable != null) {
                doDraw()
            }
        }
        if (weakBitmap != null) {
            paint.xfermode = null
            canvas.drawBitmap(weakBitmap!!, 0F, 0F, paint)
        }
    }

    // 缓存 bitmap, 避免每次 onDraw 都重新分配内存与绘图
    override fun invalidate() {
        weakBitmap?.recycle()
        maskBitmap?.recycle()
        super.invalidate()
    }

    private fun doDraw() {
        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        val scale = if (type == TYPE_ROUND)
            max(width / drawable.intrinsicHeight.toFloat(), height / drawable.intrinsicHeight.toFloat() )
        else
            width / min(drawable.intrinsicWidth, drawable.intrinsicHeight).toFloat()
        drawable.setBounds(0, 0, (scale * width).toInt(), (scale * height).toInt())
        drawable.draw(canvas)
        if (maskBitmap == null || maskBitmap!!.isRecycled) {
            maskBitmap = getBitmap()
        }
        paint.reset()
        paint.isFilterBitmap = false
        paint.xfermode = xfermode
        canvas.drawBitmap(maskBitmap!!, 0F, 0F, paint)
        weakBitmap = bitmap
        canvas.drawBitmap(bitmap, 0F, 0F, null)
        paint.xfermode = null
    }

    private fun getBitmap(): Bitmap {
        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        val paint = Paint(Paint.ANTI_ALIAS_FLAG)
        paint.color = Color.BLACK
        if (type == TYPE_ROUND) {
            canvas.drawRoundRect(
                RectF(0F, 0F, width.toFloat(), height.toFloat()),
                borderRadius.toFloat(),
                borderRadius.toFloat(),
                paint
            )
        } else {
            val hw = width / 2F
            canvas.drawCircle(hw, hw, hw, paint)
        }
        return bitmap
    }
}